﻿

#region Using Statements

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Threading;
using System.ComponentModel;
using System.Reflection;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Design;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using Freeform;
using FGame = Freeform.Game;
using XGame = Microsoft.Xna.Framework.Game;
using FComponent = Freeform.Component;

#endregion


namespace Freeform
{
    /// <summary>
    /// The camera controls where the entities appear in the viewport.
    /// </summary>
    public class Camera2D : Component, IGeometric2D
    {

        #region Members

        /// <summary>
        /// Gets the viewport that this camera belongs to.
        /// </summary>
        public virtual Viewport2D Viewport { get; private set; }


        /// <summary>
        /// Gets the world that this camera is observing.
        /// </summary>
        public virtual World World { get; private set; }


        /// <summary>
        /// Gets or sets the position of the camera.
        /// </summary>
        public Vector2 Position { get; set; }


        /// <summary>
        /// Gets or sets the orientation of the camera.
        /// </summary>
        public Single Orientation { get; set; }


        /// <summary>
        /// Gets or sets how much fits on the camera.
        /// </summary>
        public Vector2 Size { get; set; }

        #endregion


        #region Init

        /// <summary>
        /// Creates a new instance of a camera.
        /// </summary>
        /// <param name="Viewport">The viewport that this camera belongs to.</param>
        internal Camera2D(Viewport2D Viewport)
            : base(Viewport.World.ComponentList)
        {
            this.Viewport = Viewport;
            World = Viewport.World;
            IsEnabled = true;
            Viewport.Camera = this;
        }

        #endregion


        #region Update


        #endregion


        #region Utility

        /// <summary>
        /// Sets the centre-point of the camera.
        /// </summary>
        /// <param name="Position">The centre-point of the camera.</param>
        public virtual void CentreCamera(Vector2 Position)
        {
            this.Position = Position - Size / 2;
        }


        /// <summary>
        /// Applies zoom to the camera relative to the centre-point.
        /// </summary>
        /// <param name="Factor">The zoomfactor. Example: 1.5f --> Zoom in by 50%,  0.5f --> Zoom out by 50%</param>
        public virtual void Zoom(Single Factor)
        {
            // Find the centre-point of the screen.
            Vector2 Centre = Position + Size / 2;

            // Apply zoom effect.
            Size /= Factor;

            // Maintain camera centre.
            CentreCamera(Centre);
        }


        /// <summary>
        /// Transforms a point in world-space to pixel-space on the viewport.
        /// </summary>
        /// <param name="Position">The point in world-space.</param>
        /// <returns>A point in pixel-space.</returns>
        public virtual Vector2 TransformPosition(Vector2 Position)
        {
            return new Vector2((Position.X - this.Position.X) * Viewport.RenderTarget.Width / this.Size.X,
                (Position.Y - this.Position.Y) * Viewport.RenderTarget.Height / this.Size.Y);
        }


        /// <summary>
        /// Transforms a size in world-space to a size in pixels.
        /// </summary>
        /// <param name="Size">The size in world-space.</param>
        /// <returns>The size in pixels.</returns>
        public virtual Vector2 TransformSize(Vector2 Size)
        {
            return new Vector2(Size.X * Viewport.RenderTarget.Width / this.Size.X,
                Size.Y * Viewport.RenderTarget.Height / this.Size.Y);
        }

        #endregion

    }
}